package com.yvan.serverless.script;

import com.yvan.serverless.utils.FileUtilExt;
import lombok.extern.slf4j.Slf4j;
import org.graalvm.polyglot.Engine;

@Slf4j
public class ScriptContextHolder {
    ThreadLocal<ScriptContext> threadLocal = new ThreadLocal<>();
    final String distLocation;
    final int inspectPort;
    Engine engine;
    final boolean inspectEnable;

    public ScriptContextHolder(String distLocation,
                               boolean inspectEnable,
                               int inspectPort) {
        this.distLocation = distLocation;
        this.inspectPort = inspectPort;
        this.inspectEnable = inspectEnable;

        rebuildEngin();
    }

    public void rebuildEngin() {
        if (engine != null) {
            engine.close(false);
        }

        Engine.Builder builder = Engine.newBuilder()
                .allowExperimentalOptions(true);

        String srcPath = FileUtilExt.normalizePath(distLocation);
        if (srcPath.length() > 2 && srcPath.charAt(2) == ':') {
            srcPath = srcPath.substring(1);
        }
        srcPath = srcPath + "/";
        if (inspectEnable) {
            // 参数详情，见 com.oracle.truffle.tools.chromeinspector.instrument.InspectorInstrument
            builder.option("inspect", "" + inspectPort)
                    .option("inspect.Path", "")
                    .option("inspect.Secure", "false")
                    // .option("inspect.WaitAttached", "false")
                    .option("inspect.Initialization", "true")
                    .option("inspect.Internal", "true")
                    .option("inspect.SourcePath", srcPath)
                    .option("inspect.Suspend", "false");
        }

        engine = builder.build();
    }

    /**
     * 获取当前线程的脚本执行环境
     */
    public ScriptContext getCurrentScriptContext() {
        ScriptContext context = threadLocal.get();
        if (context == null || context.getEngine() != this.engine) {
            context = new ScriptContext(this, true);
            threadLocal.set(context);
        }
        return context;
    }

    /**
     * 获取当前线程的脚本执行环境
     */
    public ScriptContext getCurrentScriptContextNotClear() {
        ScriptContext context = threadLocal.get();
        if (context == null || context.getEngine() != this.engine) {
            context = new ScriptContext(this, false);
            threadLocal.set(context);
        }
        return context;
    }

    /**
     * 删除缓存的 js 模块，重新从文件系统读取内容
     */
    public void clearCurrentScriptContext() {
        threadLocal.remove();
    }
}
